[따배도] - 컨테이너 리소스 관리하기


컨테이너 리소스 관리 명령어를 배워봅시다.
(메모리, CPU, Block I/O, cAdvisor)

컨테이너 하드웨어 리소스 제한

  • 기본적으로 컨테이너는 호스트 하드웨어 리소스의 사용 제한을 받지 않습니다.

    • 컨테이너의 자원을 적절하게 제한해야 효율적인 운영을 실현할 수 있습니다.
    • docker run --help 명령어를 통해 CPU, Memory, Disk I/O를 제한할 수 있음

메모리 리소스 제한

  • 제한 단위는 b, k, m, g 로 할당
  • --memory, -m : 컨테이너가 사용할 때 최대 메모리 양을 지정
  • --memory-swap : 컨테이너가 사용할 스왑 메모리 영역에 대한 설정

    • 메모리+스왑 생략 시 메모리의 2배가 설정됨
  • --memory-reservation : —memory 값보다 적은 값으로 구성하는 소프트 제한 값 설정
  • --oom-kill-disable : OOM Kiler가 프로세스 kill 하지 못하도록 보호

CPU 리소스 제한

  • --cpus : 컨테이너에 할당할 CPU core 수를 지정
  • --cpuset-cpus : 컨테이너가 사용할 수 있는 CPU나 코어를 할당. cpu index는 0부터.
  • --cpu-share : 컨테이너가 사용하는 CPU 비중을 1024 값을 기반으로 설정

    • —cpu-share 2048 기본 값보다 두배 많은 CPU 자원을 할당

Block I/O 제한

  • --blkio-weight / blkio-weight-device : Block IO의 Quota를 설정할 수 있으며 100~1000까지 선택, default 500
  • --device-read/write-bps : 특정 디바이스에 대한 읽기와 쓰기 작업의 초당 제한을 kb, mb, gb 단위로 설정
  • --device-read/write-iops : 컨테이너의 read/write 속도의 쿼터를 설정한다.

컨테이너 사용 리소스를 확인하는 모니터링 툴

docker monitoring commands

  • docker stat : 실행중인 컨테이너의 런타임 통계를 확인

    • docker stats [OPTIONS] [CONTAINER..]
  • docker event : 도커 호스트의 실시간 event 정보를 수집해서 출력
  • cAdvisor : 구글에서 만듬

실습

부하테스트를 통한 리소스 제한 하기

부하테스트에서 사용할 컨테이너는 stress 툴을 사용

  • stress 도커 파일 만들기
FROM debian
RUN apt-get update; apt-get install stress -y
CMD ["/bin/sh", "-c", "stress -c 2"]
  • 도커 파일 빌드
$ docker build -t stress .

메모리 리소스 제한

💡

Swap Memory

모든 컴퓨터 운영체제에는 가상메모리라는 것을 사용하게 되는데
리눅스에서 가상메모리를 스왑파일시스템이라고 합니다.

  • swap 메모리 용량 제한이 실제 메모리 제한과 어떤 관련성이 있는지 확인해본다.

    • -m : 메모리 지정
    • --memory-swap : 스왑 메모리 지정
    • 즉, 아래의 예시는 전체적인 메모리 100m 중 스왑 메모리를 100를 줌으로써 스왑 메모리는 이용할 수 없는 것을 의미합니다.(200m 를 지정하였으면 스왑메모리는 100를 사용할 수 있는 것임)
    • stress --vm 1 --vm-bytes 90m -t 5s : stress 툴의 명령어 참고
$ docker run -m 100m --memory-swap 100m stress:latest stress --vm 1 --vm-bytes 90m -t 5s
  • 할당 된 메모리보다 높은 사용량을 지정하였을 때 실행 검증

    • 실행이 되지 않는 것을 확인할 수 있음(--vm-bytes 150m 부분때문에)

가끔 커널의 설정 문제로 메모리 제한 설정이 적용이 안되어서 실행이 되는 경우가 있는데,

  1. root 사용자로 진입 후 /etc/default/grub 파일 수정
  2. GRUBCMDLINELINUXDEFAULT=“cgroupenable=memory swapaccount=1” 명령어 추가
  3. update-grub 명령어 입력
  4. reboot 명령어 입력
$ docker run -m 100m --memory-swap 100m stress:latest stress --vm 1 --vm-bytes 150m -t 5s

OOM-killer

💡

out-of-memory-killer란?

리눅스에서는 안정적인 서버 운영을 위해 호스트 메모리가 부족하게 되면 프로세스를 강제 종료하게 됩니다.

  • OOM-killer로 강제 종료되는 것을 방지하기 위해 --oom-killer-disable=ture 명령을 통해 프로세스 강제 종료를 방지할 수 있습니다.
$ docker run -d -m 100M --name m4 --oom-kill-disable=true nginx
  • inspect 명령어를 통해 컨테이너 상세 확인

    • "Memory": 104857600, "MemorySwap": 209715200, : 스왑메모리 따로 지정을 안해주니 자동적으로 2배로 산정된 것을 확인할 수 있습니다.
    • "OomKillDisable": true, : OOM-killer가 비활성화 되었습니다.
$ docker inspect m4
  • 컨테이너ID를 직접 조회하는 방식으로 확인

    • oom_kill_disable 이 1 값으로 설정되어 있습니다.
$ cat /sys/fs/cgroup/memory/docker/6b2d8b686ab6c9c43fb76fa1310ab3c16ea672f86980ed5d53394e42e7f7df26/memory.oom_control

1  도커 리소스 아웃오브메모리

CPU 리소스 제한

  • CPU-index를 지정해서 컨테이너 동작시키기(예를 들어 4코어 중 n번째 코어 사용)
$ docker run --cpuset-cpus 1 --name c1 stress:latest stress --cpu 1
# 0-1 번 중 상황에 따라서 두개 중 하나를 사용
$ docker run --cpuset-cpus 0-1 --name c1 stress:latest stress --cpu 1

docker: Error response from daemon: Requested CPUs are not available - requested 1, available: 0.

위와 같은 오류가 뜨는 것은 cpu가 1개 밖에 없으므로 뜨게 됩니다.

  • htop 명령어로 CPU 점유율 확인

    • 현재 CPU가 하나이므로 CPU index가 하나밖에 보이지 않는 상태
$ htop

2  cpu 자원률 확인

  • --cpu-shares 명령어를 이용해 CPU 상대적 가중치를 할당
$ docker run --cpu-shares 2048 --name cload1 -d stress:latest # 가장 점유율 높음
$ docker run --name cload2 -d stress:latest # 점유율 보통(1024 기본 값)
$ docker run -c 512 --name cload3 -d stress:latest # 점유율 가장 낮음
  • 모니터링 툴을 이용해 확인해 봅시다.

    • CPU 1개를 기준으로 cload1 CPU는 55%, cload2 CPU는 27%, cload3 CPU는 13% 점유율을 각각 할당되어 있음
    • 상대적으로 비율을 조절하고 있습니다.
$ docker stats <컨테이너 이름 생략 가능>

3  cpu-shares 자원률 확인

Block I/O 제한

💡

명령어를 통해 리눅스 스토리지 디바이스 정보를 출력하는 방법

lsblk 명령어를 통해 리눅스 디바이스 정보를 출력할 수 있습니다.

  • lsblk 명령어를 통해 리눅스 스토리지 디바이스 정보 확인
$ lsblk
  • 컨테이너를 하나 만든 뒤, 명령어를 통해 컨테이너 IO의 속도를 조절
$ docker run -it --rm --device-write-iops /dev/xvda:10 ubuntu:latest /bin/bash
# 컨테이너 진입 후
$ dd if=/dev/zero of=file1 bs=1M count=10 oflag=direct
# 컨테이너 나오기
$ exit

4  block i,o 속도 확인

  • 조금 더 빠른 IO 컨테이너를 만든 뒤, 속도 비교

    • 위의 컨테이너는 초당 10.4 MB를 만들었지만, 해당 컨테이너는 초당 254MB를 만들면서 IO 속도가 증가한 것을 확인할 수 있습니다.
$ docker run -it --rm --device-write-iops /dev/xvda:100 ubuntu:latest /bin/bash
# 컨테이너 진입 후
$ dd if=/dev/zero of=file1 bs=1M count=10 oflag=direct

5  block i,o 속도 확인

cAdvisor 실행

  • 컨테이너 실행

    • 참고: 스왑 메모리 미지정 상태에서 500MB 할당되어, 스왑 메모리는 2배를 가지게 됨
$ docker run -it --rm --device-write-iops /dev/xvda:100 -m 500m --name c1 -d ubuntu:latest /bin/bash
  • cAdvisor 설치 후, 웹에서 GUI 화면 확인

    • 참고: cAdvisor는 구글에서 만든 컨테이너 분석 툴입니다.
    • 쿠버네티스의 kubelet에서는 기본적으로 설치되어 있습니다.
VERSION=v0.36.0 # use the latest release version from https://github.com/google/cadvisor/releases
sudo docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  --privileged \
  --device=/dev/kmsg \
  gcr.io/cadvisor/cadvisor:$VERSION
  • cAdvisor 접속하기

    • 웹 브라우저를 통해 접속이 가능합니다.
<퍼블릭 아이피>:8080(포트번호)

실습 과제

  • mysql 이미지를 사용하여

    1. 메모리 200m
    2. 스왑메모리 300m
    3. CPU 1개 사용한 후
    4. docker stats 명령어로 리소스 확인
$ docker run --name db -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=pass -m 200m --memory-swap 300m --cpus 1 mysql:latest
# 자원 확인
$ docker stats

6  디비자원화깅ㄴ

Reference

swap 메모리 설명
swap 메모리 설정
stress 툴 명령어
docker 자원 할당 에러
리눅스 스토리지 디바이스 출력 명령어
cAdvisor-github


Hello, I'm@nickhealthy
개발자를 꿈꾸고, 파이썬과 클라우드에 관심이 많은 비전공자

Github